package xutils

import (
	"time"
)

var _EPOCH uint64 = 1288834974657

var _TIMESTAMP_BITS uint64 = 42
var _MACHINE_ID_BITS uint64 = 10
var _SEQUENCE_BITS uint64 = 12

var _TIMESTAMP_SHIFT uint64 = 64 - _TIMESTAMP_BITS
var _MACHINE_ID_MAX uint64 = 0xFFFFFFFFFFFFFFFF ^ (0xFFFFFFFFFFFFFFFF << _MACHINE_ID_BITS)
var _MACHINE_ID_SHIFT uint64 = _SEQUENCE_BITS
var _SEQUENCE_MASK uint64 = 0xFFFFFFFFFFFFFFFF ^ (0xFFFFFFFFFFFFFFFF << _SEQUENCE_BITS)

var machine_id uint64 = 0
var machine_factor uint64 = 0
var sequence uint64 = 0
var last_ts uint64 = _EPOCH


/**
 * 为当前实例设置一个全局唯一的 MACHINE_ID。
 */
func UUIDInit(mid int) error {
	// ASSERT: mid >= 0 || uint64(mid) <= _MACHINE_ID_MAX)
	machine_id = uint64(mid) & _MACHINE_ID_MAX
	machine_factor = machine_id << _MACHINE_ID_SHIFT

	return nil
}

/**
 * 生成一个 UUID。
 */
func UUIDGenerate() uint64 {
	ts := uint64(time.Now().UnixNano() / 1000000)
	if ts < last_ts {
		// 系统时间被向后倒拨了，此时不能工作
		return 0
	}

	if ts == last_ts {
		sequence = (sequence + 1) & _SEQUENCE_MASK
		if sequence == 0 {
			// 在同一个毫秒内的序列号全部用光，只能等到下一毫秒
			for ts <= last_ts {
				ts = uint64(time.Now().UnixNano() / 1000000)
			}
		}
	} else {
		sequence = 0
	}
	last_ts = ts

	return ((ts - _EPOCH) << _TIMESTAMP_SHIFT) | machine_factor | sequence
}
